package com.talent.core.protocol.mqtt.codec;

import com.talent.core.protocol.mqtt.codec.decoder.*;
import com.talent.core.protocol.mqtt.enums.TlMqttMessageType;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @ClassName：MessageCodec
 * @Author: hszhou
 * @Date: 2024/11/15 16:16
 * @Description: mtt的解码器
 */
public class TlMqttMessageCodec extends ByteToMessageDecoder {

    private static final  Logger logger = LoggerFactory.getLogger(TlMqttMessageCodec.class);


    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception {
        //如果刻度字节小于2个字节 说明还没有读取到正确的包 因为固定头最少为2个字节
        if(in.readableBytes()<2){
            in.resetReaderIndex();
            return;
        }
        //标记一下 后面读取的时候 如果没有读取到正确的值的时候 就可以回到原来的位置 重新涂
        in.markReaderIndex();
        short type = in.readUnsignedByte();
        int remainingLength = 0;
        int multiplier = 1;
        short digit;
        int loops = 0;
        do {
            // 读取一个字节
            digit = in.readUnsignedByte();
            // 提取低7位并计算实际值
            remainingLength += (digit & 127) * multiplier;
            // 更新乘数，用于多字节情况
            multiplier *= 128;
            loops++;
        } while ((digit & 128) != 0 && loops < 4);
        //判断剩余可以字节是否小于报文中的字节数 如果是
        if (in.readableBytes()  < remainingLength) {
            in.resetReaderIndex();
            return ;
        }


        int messageType = type >> 4;
        TlMqttMessageType MESSAGE_TYPE = TlMqttMessageType.getByValue(messageType);
        logger.debug("接收到的消息类型是【{}】",MESSAGE_TYPE);
        Object req=null;
        switch (MESSAGE_TYPE){
            case CONNECT:
                req = new TlMqttConnectDecoder().build(in, type, remainingLength);
                break;
            case DISCONNECT:
                req= new TlMqttDisConnectDecoder().build(in,type,remainingLength);
                break;
            case PUBLISH:
                req = new TlMqttPublishDecoder().build(in,type,remainingLength);
                break;
            case PUBACK:
                req = new TlMqttPubAckDecoder().build(in,type,remainingLength);
                break;
            case PUBREC:
                req = new TlMqttPubRecDecoder().build(in,type,remainingLength);
                break;
            case PUBREL:
                req = new TlMqttPubRelDecoder().build(in,type,remainingLength);
                break;
            case PUBCOMP:
                req = new TlMqttPubCompDecoder().build(in,type,remainingLength);
                break;

            case SUBSCRIBE:
                req = new TlMqttSubscribeDecoder().build(in,type,remainingLength);
                break;
            case UNSUBSCRIBE:
                req = new TlMqttUnSubscribeDecoder().build(in,type,remainingLength);
                break;
            case PINGREQ:
                req = new TlMqttHeartBeatDecoder().build(in,type,remainingLength);
                break;
            default:
                logger.info("出现了错误的数据类型");
                break;
        }
        in.markReaderIndex();
        out.add(req);
    }




}

